import random
import re
from flask import abort, jsonify
from flask import request, current_app

from info.lib.yuntongxun.sms import CCP
from info.models import User
from info.utils.response_code import RET
from . import passport_bp
from info.utils.captcha.captcha import captcha
from info import redis_store,constants

# 127.0.0.1:5000/passport/image_code?code_id=uuid编码
@passport_bp.route('/image_code')
def get_image_code():
    """获取验证码图片的后端接口（GET）"""

    """
    1,获取参数
        1.1获取code_id,全球惟一的编码（uuid）
    2,校验参数
        2.1f非空判断，判断code_id是否有值
    3,逻辑处理
        3.1生成验证码图片并生成图片真实值
        3.2以code_id作为key将生成验证码图片的真实值（数字字母）存储的redis数据库中
    4,返回值
        4.1返回验证码图片
    """

    # 1.1获取code_id,全球惟一的编码（uuid）
    code_id = request.args.get('code_id', '')
    print(code_id)

    # 2.1非空判断，判断code_id是否有值
    if not code_id:
        current_app.logger.error("参数不足")
        # 参数不存在，404错误
        abort(404)

    #3.1生成验证码图片并生成图片真实值
    image_name, real_image_code, image_data = captcha.generate_captcha()
    #3.2以code_id作为key将生成验证码图片的真实值（数字字母）存储的redis数据库中
    try:
        redis_store.setex("imageCodeId_%s" % code_id,constants.IMAGE_CODE_REDIS_EXPIRES, real_image_code)
    except Exception as e:
        current_app.logger.error(e)
        abort(500)

    #4.1返回验证码图片
    return image_data


# 127.0.0.1:5000/passport/sms_code
@passport_bp.route('/sms_code')
def send_sms_code():
    """发送短信验证码到后端接口"""

    """
    1,获取参数
      1.1用户帐号手机号码mobile,用户填写的图片验证码值：image_code,编号UUID：image_code_id
    2,校验参数
      2.1非空判断mobile, image_code, image_code_id
      2.2手机格式判断
    3,逻辑处理
        3.1根据编号去redis数据库获取图片验证码的真实值（正确值）
            3.1.1真实值有值：将这个值从redis中删除（防止其他人多次拿验证码值来验证）
            3.1.2真实值没有值：图片验证码过期了
        3.2拿用户填写的图片验证码值和redis中获取的真实值进行比较
        3.3不相等，告诉前端图片验证码填写错误
            3.3.1判断用户是否注册过，如果已经注册,进行下一步登录程序，否则,需要先进行注册
        3.4相等,生成6位随机短信验证码，并发送短信验证码(这里需要把6位验证码存储到redis数据库中)

    4,返回值
        4.1发送短信验证码成功
    """

    #上传数据是json类型
    #1.1用户帐号手机号码mobile,用户填写的图片验证码值：image_code,编号UUID：image_code_id
    #json.loads(request.data)
    #可以接受前端上传的json格式数据，json字符串转换成python对象
    param_dict = request.json
    #手机号码
    mobile = param_dict.get("mobile", "")
    #用户填写的图片验证码值
    image_code = param_dict.get("image_code", "")
    #uuid编号
    image_code_id = param_dict.get("image_code_id", "")


    #2.1非空判断mobile, image_code, image_code_id
    if not all([mobile, image_code, image_code_id]):
        # 记录日志
        current_app.logger.error("参数不足")
        #给调用者返回json格式的错误信息
        return jsonify({"error":RET.PARAMERR, "errmsg": '参数不足'})

    #2.2手机号码格式的判断
    if re.match('1[35789][0-9]{9}',mobile):
        current_app.logger.error("手机格式错误")
        return jsonify(errno=RET.PARAMERR, errmsg="手机格式错误")


    #3,逻辑处理
    #3.1根据编号去redis数据库获取图片验证码的真实值（正确值）
    try:
        real_image_code = redis_store.get("imageCodeID_%s" % image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="从redis中获取图片真实值异常")
    #3.1.1真实值有值：将这个值从redis中删除（防止其他人多次拿验证码值来验证）
    if real_image_code:
        redis_store.delete("imageCodeID_%s" % image_code_id)
    #3.1.2真实值没有值：图片验证码过期了
    else:
        return jsonify(errno=RET.NODATA, errmsg="图片验证码过期了")
    # 3.2拿用户填写的图片验证码值和redis中获取的真实值进行比较
    #细节1：全部按照小写格式进行比较（忽略大小写）
    #细节2：redis对象创建的时候设置decode_response=True
    if real_image_code.lower() != image_code.lower():
        # 3.3不相等，告诉前端图片验证码填写错误
        return jsonify(errno=RET.DATAERR, errmsg="填写图片验证码错误")
    # 3.3.1判断用户是否注册过，如果已经注册,进行下一步登录程序，否则,需要先进行注册
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="从mysql中查询用户异常")
    #如果已经注册，就不在发送验证码，直接进行登录
    if user:
        return jsonify(errno=RET.DATAEXIST,errmsg="手机号码已经注册请登录")
    # 3.4相等,生成6位随机短信验证码，并发送短信验证码(这里需要把6位验证码存储到redis数据库中)
    #生成6位随机短信验证码
    sms_code = random.randit(0, 999999)
    #不足6位前面补0
    sms_code = "%06d" % sms_code
    try:
        result = CCP().send_tempalate_sms(mobile, {sms_code, constants.SMS_CODE_REDIS_EXPIRES/60},1)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR,errmsg="云通讯发送短信失败")

    if result != 0:
        return jsonify(errno=RET.THIRDERR, errmsg="云通讯发短信失败")

    #3.4将生成的6位随机短信验证码存储到redis数据库
    try:
        #SMS_CODE_123445678912每个用户这个key都不一样
        redis_store.setex("SMS_CODE_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="存贮验证码异常")
    #4返回值
    return jsonify(erno=RET.OK,errmsg="发送短信验证码成功，注意查收")